package com.zb.zeus.common.security.handler;

import com.zb.zeus.common.core.constant.HttpStatus;
import com.zb.zeus.common.core.exception.*;
import com.zb.zeus.common.core.utils.StringUtils;
import com.zb.zeus.common.core.web.domain.AjaxResult;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Optional;

/**
 * 全局异常处理器
 *
 * @author zb.zeus
 */
@RestControllerAdvice
@ConditionalOnMissingBean(ZeusExceptionHandler.class)
public class GlobalExceptionHandler implements ZeusExceptionHandler {


    /**
     * 基础异常
     */
    @ExceptionHandler(BaseException.class)
    public AjaxResult baseException(BaseException e) {
        logger.error("base exception", e);
        Integer code = Optional.ofNullable(e.getCode())
                .filter(NumberUtils::isDigits).map(NumberUtils::createInteger)
                .orElse(HttpStatus.BASE_EXCEPTION);
        return AjaxResult.error(code, e.getDefaultMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(CustomException.class)
    public AjaxResult businessException(CustomException e) {
        logger.error("business exception", e);
        if (StringUtils.isNull(e.getCode())) {
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e) {
        logger.error("occur unexpect error", e);
        return AjaxResult.error(HttpStatus.ERROR, e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public AjaxResult validatedBindException(BindException e) {
        logger.error(e.getMessage(), e);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(HttpStatus.BAD_REQUEST, message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validExceptionHandler(MethodArgumentNotValidException e) {
        logger.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(HttpStatus.BAD_METHOD, message);
    }

    /**
     * 权限异常
     */
    @ExceptionHandler(PreAuthorizeException.class)
    public AjaxResult preAuthorizeException(PreAuthorizeException e) {
        logger.error("pre authorize exception", e);
        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限，请联系管理员授权");
    }

    /**
     * 非法参数异常
     */
    @ExceptionHandler({IllegalArgumentException.class, IllegalStateException.class})
    public AjaxResult illegalArgumentException(RuntimeException e) {
        logger.error("illegal state exception", e);
        return AjaxResult.error(HttpStatus.ILLEGAL_PARAM, e.getMessage());
    }

    /**
     * 演示模式异常
     */
    @ExceptionHandler(DemoModeException.class)
    public AjaxResult demoModeException(DemoModeException e) {
        logger.error("demoModeException", e);
        return AjaxResult.error(HttpStatus.BAD_REQUEST, "演示模式，不允许操作");
    }

}
